package com.sayice.icemusic.service.music.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sayice.icemusic.pojo.Music;
import com.sayice.icemusic.service.music.MusicService;
import com.sayice.icemusic.util.LyricUtils;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.springframework.util.DigestUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 酷狗音乐服务
 *
 * @author shubing
 */
public class KuGouMusicServiceImpl implements MusicService {
    private static final KuGouMusicServiceImpl INSTANCE = new KuGouMusicServiceImpl();
    
    /**
     * 音乐来源
     */
    private static final String SOURCE_NAME = "酷狗音乐";
    
    /**
     * 预搜索地址 (获取 Cookie)
     */
    private static final String PRE_SEARCH_ADDRESS = "https://complexsearch.kugou.com/v2/search/song";
    
    /**
     * 搜索地址模板
     */
    private static final String SEARCH_ADDRESS_TEMPLATE = "https://wwwapi.kugou.com/yy/index.php?r=play/getdata&hash=%s&album_id=%s&_=%d";
    
    /**
     * 音乐信息正则
     */
    private final static Pattern MUSIC_INFOS_PATTERN = Pattern.compile("callback123\\((.*)\\)");
    
    private KuGouMusicServiceImpl() {
    }
    
    public static KuGouMusicServiceImpl getInstance() {
        return INSTANCE;
    }
    
    /**
     * 搜索音乐
     *
     * @param name   音乐名
     * @param sorter 排序方式
     * @return 搜索到的音乐列表
     */
    @Override
    public List<Music> search(String name, String sorter) {
        long time = System.currentTimeMillis();
        List<Music> musicList = new ArrayList<>();
        try {
            Response preSearchResponse = Jsoup.connect(PRE_SEARCH_ADDRESS)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53")
                    .data(new HashMap<String, String>(32) {{
                        put("callback", "callback123");
                        put("keyword", name);
                        put("page", "1");
                        put("pagesize", "30");
                        put("bitrate", "0");
                        put("isfuzzy", "0");
                        put("tag", "em");
                        put("inputtype", "0");
                        put("platform", "WebFilter");
                        put("userid", "0");
                        put("clientver", "2000");
                        put("iscorrection", "1");
                        put("privilege_filter", "0");
                        put("srcappid", "2919");
                        put("clienttime", String.valueOf(time));
                        put("mid", String.valueOf(time));
                        put("uuid", String.valueOf(time));
                        put("dfid", "-");
                        put("signature", getSignature(name, time));
                    }})
                    .execute();
            String preSearchBody = preSearchResponse.body();
            Matcher m = MUSIC_INFOS_PATTERN.matcher(preSearchBody);
            if (m.find()) {
                JSONArray listsJSONArray = JSON.parseObject(m.group(1)).getJSONObject("data").getJSONArray("lists");
                listsJSONArray.forEach(musicInfo -> {
                    JSONObject info = (JSONObject) musicInfo;
                    String searchAddress = String.format(SEARCH_ADDRESS_TEMPLATE, info.getString("FileHash"), info.getString("AlbumID"), time);
                    try {
                        Response mp3UrlResponse = Jsoup.connect(searchAddress)
                                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53")
                                .header("cookie", "kg mid=671056f931bdd92c3d9cfbc1996e21ec; kg dfid=34dT144TKakk4bjeOl0X7qkb; kg dfid collect=d41d8cd98f00b204e9800998ecf8427e; Hm lvt aedee6983d4cfc62f509129360d6bb3d=1630837212,1630926700,1630938173; Hm lpvt aedee6983d4cfc62f509129360d6bb3d=1630941313; kg mid temp=671056f931bdd92c3d9cfbc1996e21ec; ACK SERVER 10016=%7B%22list%22%3A%5B%5B%22gzreg-user.kugou.com%22%5D%5D%7D; ACK SERVER 10017=%7B%22list%22%3A%5B%5B%22gzverifycode.service.kugou.com%22%5D%5D%7D; ACK SERVER 10015=%7B%22list%22%3A%5B%5B%22gzlogin-user.kugou.com%22%5D%5D%7D")
                                .execute();
                        String mp3UrlBody = mp3UrlResponse.body();
                        JSONObject data = JSON.parseObject(mp3UrlBody).getJSONObject("data");
                        String musicId = data.getString("audio_id");
                        String musicName = data.getString("song_name");
                        String mp3Url = data.getString("play_url").replace("\\", "");
                        String artistName = data.getString("author_name");
                        String albumName = data.getString("album_name");
                        String imgUrl = data.getString("img").replace("\\", "");
                        String[][] lyrics = LyricUtils.parse(data.getString("lyrics"));
                        Music music = new Music(musicId, musicName, mp3Url, artistName, albumName, imgUrl, SOURCE_NAME, lyrics);
                        musicList.add(music);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return musicList;
    }
    
    private String getSignature(String musicName, long currentTime) {
        String[] sign = {"NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt",
                "bitrate=0",
                "callback=callback123",
                "clienttime=" + currentTime,
                "clientver=2000",
                "dfid=-",
                "inputtype=0",
                "iscorrection=1",
                "isfuzzy=0",
                "keyword=" + musicName,
                "mid=" + currentTime,
                "page=1",
                "pagesize=30",
                "platform=WebFilter",
                "privilege_filter=0",
                "srcappid=2919",
                "tag=em",
                "userid=0",
                "uuid=" + currentTime,
                "NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt"};
        return DigestUtils.md5DigestAsHex(String.join("", sign).getBytes());
    }
}
